home *** CD-ROM | disk | FTP | other *** search
/ Linux Cubed Series 2: Applications / Linux Cubed Series 2 - Applications.iso / utils / console / splitvt-.000 / splitvt- / splitvt-1.6.1 / splitvt.c < prev    next >
Encoding:
C/C++ Source or Header  |  1995-01-09  |  16.5 KB  |  713 lines

  1.  
  2. /* 
  3.     splitvt
  4.  
  5.   A fun utility designed to split your screen into twin shells.
  6.  
  7.                 -Sam Lantinga  10/5/93
  8. */
  9.  
  10. static char *version=
  11. "@(#)Splitvt 1.6.1   1/8/95  -Sam Lantinga   (slouken@cs.ucdavis.edu)\n";
  12.  
  13. #include    <sys/types.h>
  14. #include    <sys/time.h>
  15. #include    <sys/wait.h>
  16. #include    <fcntl.h>
  17. #include    <signal.h>
  18. #include    <stdio.h>
  19. #include    <errno.h>
  20. #include    <pwd.h>
  21. #ifdef HAVE_UNISTD_H
  22. #include    <unistd.h>
  23. #endif
  24. #include    "splitvt.h"
  25. #include    "vt100.h"
  26. #include    "vtmouse.h"
  27.  
  28. /* With xterm support, cut and paste is disabled and the title bar is
  29.    reset to the string "xterm" after splitvt quits.  Not desirable in
  30.    some cases.. ;^)
  31. */
  32. #define X_SUPPORT    /* Comment this line if you don't want xterm support */
  33. #define XTITLE        /* Define this for an xterm title bar */
  34.  
  35. #ifdef NEED_SELECT_H
  36. #include    <sys/select.h>
  37. #endif
  38.  
  39. #ifdef NEED_INET_H
  40. #include    <sys/inet.h>
  41. #endif
  42.  
  43. #ifndef SIGCLD    /* BSD */
  44. #define SIGCLD SIGCHLD
  45. #endif
  46.  
  47. extern char tty_name[];            /* From misc.c about get_master_pty() */
  48. static char upper_tty[64]={'\0'};    /* tty_name of the upper window */
  49. static char lower_tty[64]={'\0'};    /* tty_name of the lower window */    
  50. static struct passwd *pw=NULL;        /* Our passwd entry pointer */
  51.  
  52. static void finish(), move_bar(), winch();
  53. extern void lock_screen();        /* From lock.c */
  54. void normal_input();
  55. static int  insert_dash();
  56. static int  isalive();
  57. char extract();
  58. void splitvtrc();
  59.  
  60. void (*do_input)() = normal_input;
  61.  
  62. static char selection[BUFSIZ];        /* Screen selection buffer */
  63.  
  64. static int topok=1, bottomok=1;        /* I/O flags */
  65. static int toppid=0, bottompid=0;    /* Children */
  66. static int ttyfd=0, thisfd;        /* I/O file descriptors */
  67. static int topfd, bottomfd;        /* Master file descriptors */
  68.  
  69. /* Special characters */
  70. char     command_c=COMMAND,
  71.     switch_c=SWITCH, 
  72.     quote_c=QUOTE; 
  73. int     dologin=0;        /* Do the shells run as login shells? */
  74.  
  75. /* The command to run in each window */
  76. char *upper_args[256]={NULL}, *lower_args[256]={NULL};
  77. int upper_empty=1, lower_empty=1;
  78.  
  79. void print_usage(argv)
  80. char *argv;
  81. {
  82.     fprintf(stderr, "\nUsage: %s [options] [shell]\n\n", argv);
  83.     fprintf(stderr, "Options:\n");
  84.     fprintf(stderr, "\t-s numlines\t\tSets 'numlines' to the number of lines\n");
  85.     fprintf(stderr, "\t\t\t\tin the top window.  This number will\n");
  86.     fprintf(stderr, "\t\t\t\tbe modified if the screen isn't big\n");
  87.     fprintf(stderr, "\t\t\t\tenough to handle the full size.\n\n");
  88.     fprintf(stderr, "\t-upper command\t\tRuns 'command' in the upper window\n");
  89.     fprintf(stderr, "\t-lower command\t\tRuns 'command' in the lower window\n");
  90.     fprintf(stderr, "\t-login\t\t\tRuns programs as if they were login shells\n");
  91.     fprintf(stderr, "\t-nologin\t\tOverrides \"set login on\" in startup file\n");
  92.     fprintf(stderr, "\t-rcfile file\t\tLoads 'file' at startup instead of ~/.splitvtrc\n");
  93.     fprintf(stderr, "\t-norc\t\t\tSuppresses loading your startup file\n");
  94.     fprintf(stderr, "\t-v\t\t\tPrint out the version number\n");
  95.     fprintf(stderr, "\n");
  96.     exit(1);
  97. }
  98.  
  99.  
  100. main(argc, argv)
  101. int argc;
  102. char *argv[];
  103. {
  104.     extern int errno, optind;
  105.     extern char *optarg;
  106.  
  107.     int i, len, maxfds, numready;
  108.     char buffer[BUFSIZ], *ptr;
  109.     struct timeval tv, *tvptr;
  110.     fd_set read_mask;
  111.     static struct passwd pwdata;    /* Our passwd entry */
  112.  
  113.     struct event X_event;
  114.  
  115. #ifdef NEED_INET_H
  116.         /* There is a bug in the Wallabong Group's implementation
  117.            of select().  It will not work properly with fd 0 */
  118.  
  119.         if ( (ttyfd=dup(0)) < 0 )
  120.         {
  121.                 perror("dup() error");
  122.                 exit(2);
  123.         }
  124. #endif
  125.  
  126.     /* First, get default options from ~/.splitvtrc */
  127.     for ( i=1; argv[i]; ++i ) {
  128.         if ( strcmp(argv[i], "-norc") == 0 ) {
  129.             i=0;
  130.             break;
  131.         } else if ( strcmp(argv[i], "-rcfile") == 0 ) {
  132.             if ( ! argv[++i] )
  133.                 print_usage(argv[0]);
  134.             startupfile=argv[i];
  135.         }
  136.     }
  137.     if ( i )
  138.         splitvtrc();
  139.  
  140.     /* Parse command line options */
  141.     while ( (i=getopt(argc, argv, "n:u:l:r:s:vh")) != EOF )
  142.     {
  143.         switch (i)
  144.         {
  145.             case 'n': if ( strcmp(optarg, "ologin") == 0 )
  146.                     dologin=0;
  147.                   else if ( strcmp(optarg, "orc") != 0 )
  148.                     print_usage(argv[0]);
  149.                   /* Already handled above */
  150.                   break;
  151.             case 'u': if ( strcmp(optarg, "pper") != 0 )
  152.                     print_usage(argv[0]);
  153.                   tokenize(upper_args, argv[optind++], " ");
  154.                   upper_empty=0;
  155.                   break;
  156.             case 'l': if ( strcmp(optarg, "ower") == 0 ) {
  157.                       tokenize(lower_args, 
  158.                             argv[optind++], " ");
  159.                       lower_empty=0;
  160.                   } else if ( strcmp(optarg, "ogin") == 0 ) {
  161.                     dologin=1;
  162.                   } else
  163.                     print_usage(argv[0]);
  164.                   break;
  165.             case 'r': if ( strcmp(optarg, "cfile") != 0 )
  166.                     print_usage(argv[0]);
  167.                   else /* Already handled above */
  168.                     ++optind;
  169.                   break;
  170.             case 's': UU_lines=atoi(optarg);
  171.                   break;
  172.             case 'v': printf("%s", version+4);
  173.                   exit(0);
  174.                   break;
  175.             case 'h':
  176.             default:  print_usage(argv[0]);
  177.                   break;
  178.         }
  179.     }
  180.     argv+=(optind-1);
  181.  
  182.     /* Retrieve and save our passwd entry */
  183.     if ( (pw=(struct passwd *)getpwuid(getuid())) == NULL ) {
  184.         fprintf(stderr, 
  185.         "Warning: Can't find your passwd entry; no utmp logging.\n");
  186.         sleep(2);
  187.     } else { /* Save the passwd entry for future reference */
  188.         d_copy((char *)pw, (char *)&pwdata, sizeof(pwdata));
  189.         pw=(&pwdata);
  190.     }
  191.  
  192.     if ( tty_getmode(ttyfd) < 0 ) 
  193.     {
  194.         fprintf(stderr, "Can't get terminal settings.\n");
  195.         exit(2);
  196.     }
  197.     (void) tty_raw(0);   /* Set the tty raw here to prevent lost input */
  198.  
  199.     if ( (ptr=init_vt100()) != NULL )
  200.     {
  201.         if ( tty_reset(0) < 0 )    
  202.             (void) tty_sane(0);
  203.  
  204.         fprintf(stderr, "\rCan't initialize screen: %s\n", ptr);
  205.         exit(3);
  206.     }
  207. #ifdef X_SUPPORT
  208. #ifdef XTITLE
  209.     /* Make the title bar the version string, strip extraneous info. */
  210.     strcpy(buffer, version+4);
  211.     buffer[39]='\0';
  212.     (void) event_init(stdin, stdout, buffer);
  213. #else
  214.     (void) event_init(stdin, stdout, NULL);
  215. #endif
  216. #endif /* X_SUPPORT */
  217.     selection[0]='\0';
  218.  
  219.     if ( argv[1] ) {
  220.         if ( upper_empty ) {
  221.             for ( i=0; argv[i+1]; ++i )
  222.                 upper_args[i]=argv[i+1];
  223.             upper_args[i]=NULL;
  224.         }
  225.         if ( lower_empty ) {
  226.             for ( i=0; argv[i+1]; ++i )
  227.                 lower_args[i]=argv[i+1];
  228.             lower_args[i]=NULL;
  229.         }
  230.     } else {
  231.         if ( upper_args[0] == NULL ) {
  232.             if (((upper_args[0]=(char *)getenv("SHELL")) == NULL) ||
  233.                  (*upper_args[0] == '\0') )
  234.                 upper_args[0]=SHELL;
  235.             upper_args[1]=NULL;
  236.         }
  237.         if ( lower_args[0] == NULL ) {
  238.             if (((lower_args[0]=(char *)getenv("SHELL")) == NULL) ||
  239.                  (*lower_args[0] == '\0') )
  240.                 lower_args[0]=SHELL;
  241.             lower_args[1]=NULL;
  242.         }
  243.     }
  244.     if ( dologin ) {
  245.         (void) insert_dash(upper_args);
  246.         (void) insert_dash(lower_args);
  247.     }
  248. #ifdef NEED_INET_H
  249.     signal(SIGCLD, SIG_IGN);
  250. #endif
  251.  
  252.     (void) remove_me();
  253.     if ( (topfd=pty_open(upper_args, &toppid, UPPER)) < 0 )
  254.     {
  255.         end_vt100();
  256.         switch (errno) {
  257.            case EIO:
  258.            case EPERM:
  259.            case ENOENT:
  260.             fprintf(stderr, "No available pseudo terminals.\n");
  261.             break;
  262.             case EAGAIN:
  263.             fprintf(stderr, "No more processes, try again later.\n");
  264.             break;
  265.            default:
  266.             perror("pty_open() error");
  267.         }
  268.         finish(0);
  269.     } else if ( pw ) {
  270.         (void) strcpy(upper_tty, tty_name);
  271.         (void) addutmp(pw->pw_name, pw->pw_uid, upper_tty);
  272.     }
  273.  
  274.     if ( (bottomfd=pty_open(lower_args, &bottompid, LOWER)) < 0 )
  275.     {
  276.         end_vt100();
  277.         switch (errno) {
  278.            case EIO:
  279.            case EPERM:
  280.            case ENOENT:
  281.             fprintf(stderr, "No available pseudo terminals.\n");
  282.             break;
  283.             case EAGAIN:
  284.             fprintf(stderr, "No more processes, try again later.\n");
  285.             break;
  286.            default:
  287.             perror("pty_open() error");
  288.         }
  289.         finish(0);
  290.     } else if ( pw ) {
  291.         (void) strcpy(lower_tty, tty_name);
  292.         (void) addutmp(pw->pw_name, pw->pw_uid, lower_tty); 
  293.     }
  294.     thisfd=topfd;
  295.  
  296. #if defined(_POSIX_SOURCE) || defined(m88k)
  297. #include <limits.h>
  298.     /* This is lifted from Richard Stevens. -Thanks! */
  299. #ifdef OPEN_MAX
  300.     maxfds=OPEN_MAX;
  301. #else
  302. #define OPEN_MAX_GUESS 256 /* if OPEN_MAX is indeterminate */
  303.                            /* this may be inadequate       */
  304.     if ( (maxfds = sysconf(_SC_OPEN_MAX)) < 0) {
  305.         maxfds=OPEN_MAX_GUESS;
  306.     }
  307. #endif
  308. #else /* Not POSIX SOURCE */
  309. #if defined(SOLARIS) || defined(HAVE_BSDTTY_H) || defined(HP_UX)
  310.         maxfds=32;              /* Any comments?  This is a WAG */
  311. #else
  312.         maxfds=getdtablesize();
  313. #endif
  314. #endif /* _POSIX_SOURCE */
  315.  
  316.         /* Set select() timeout, and zero out the read mask */
  317. #ifdef NEED_INET_H
  318.         tv.tv_sec=3;
  319.         tv.tv_usec=0;
  320.         tvptr=&tv;
  321. #else
  322.         tvptr=NULL;
  323. #endif
  324.     signal(SIGHUP, finish);
  325.     signal(SIGINT, finish);
  326.     signal(SIGQUIT, finish);
  327.     signal(SIGTERM, finish);
  328.     signal(SIGSEGV, finish);
  329. #ifdef SIGBUS
  330.     signal(SIGBUS, finish);
  331. #endif
  332. #ifdef SIGWINCH
  333.     signal(SIGWINCH, winch);
  334. #endif
  335.     for ( SET_WIN(); (topok || bottomok); )
  336.     {
  337.         FD_ZERO(&read_mask);
  338.         FD_SET(ttyfd, &read_mask);
  339.  
  340.         /* Make sure the children are still alive */
  341.         if ( ! isalive() )
  342.             break;
  343.  
  344.         if ( topok )
  345.             FD_SET(topfd, &read_mask);
  346.  
  347.         if ( bottomok )
  348.             FD_SET(bottomfd, &read_mask);
  349.  
  350.                 if ( (numready=select(maxfds, &read_mask, NULL, NULL, tvptr))
  351.                                                                         <= 0 )
  352.                 {
  353. #ifndef NEED_INET_H                     /* Wallabong select() is buggy */
  354.                         switch (errno)
  355.                         {
  356.                                 case EIO:    /* The program is finished. */
  357.                                                 break;
  358.                                 case EINTR:  /* Probably SIGWINCH */
  359.                                                 break;
  360.                                 default:        perror("select() error");
  361.                                                 fprintf(stderr, "\r");
  362.                                                 break;
  363.                         }
  364.                         if ( errno != EINTR )
  365.                                 finish(0);
  366.             else
  367.                 continue;
  368. #endif
  369.                 }
  370.  
  371.  
  372.         if ( FD_ISSET(ttyfd, &read_mask) )
  373.         {
  374.             do {
  375.                 if ( (buffer[0]=event_getc(&X_event)) == EOF )
  376.                     finish(0);
  377.  
  378.                 if ( X_event.happening ) {
  379.                     /* Work only on button press */
  380.                     if ( ! BUTTON_ISSET(X_event, RELEASE) ) {
  381.                     /* Mouse click in which winow? */
  382.                         if ( X_event.x > WU_lines ) { 
  383.                             if ( bottomok )
  384.                                 thisfd=bottomfd;
  385.                             SET_WIN();
  386.                         }
  387.                         else if (X_event.x < WU_lines)
  388.                         { 
  389.                             if ( topok )
  390.                                 thisfd=topfd;
  391.                             SET_WIN();
  392.                         }
  393.                         if ( BUTTON_ISSET(X_event, BUTTON_2) )
  394.                             write(thisfd, selection, strlen(selection));
  395.                     }
  396. #ifdef REPORT_SELECTION
  397.                     if ( (X_event.button_state&SELECTED) == SELECTED ) {
  398.                         vt_setsel(selection, BUFSIZ-1,
  399.                                 X_event.selection.begin_row, 
  400.                                 X_event.selection.end_row, 
  401.                                 X_event.selection.begin_col, 
  402.                                 X_event.selection.end_col); 
  403.                     }
  404. #endif
  405.                 } else {
  406.                     do_input(buffer[0]);
  407.                 }
  408.             } while (terminal_input);
  409.         }
  410.  
  411.         if  ( FD_ISSET(bottomfd, &read_mask) )
  412.         {
  413.             if ( (len=read(bottomfd, buffer, BUFSIZ)) <= 0 )
  414.             {
  415.                 switch (errno)
  416.                 {
  417.                     case EIO: /*break;*/
  418.                     default:  if ( isalive() < 0 )
  419.                             finish(0);
  420.                 }
  421.             }
  422.             else {
  423.                 (void) vt_write(LOWER, buffer, len, &bottomfd);
  424.                 if ( thisfd == topfd )
  425.                     SET_WIN();
  426.             }
  427.         }
  428.  
  429.         if  ( FD_ISSET(topfd, &read_mask) )
  430.         {
  431.             if ( (len=read(topfd, buffer, BUFSIZ)) <= 0 )
  432.             {
  433.                 switch (errno)
  434.                 {
  435.                     case EIO: /*break;*/
  436.                     default:  if ( isalive() < 0 )
  437.                             finish(0);
  438.                 }
  439.             }
  440.             else {
  441.                 (void) vt_write(UPPER, buffer, len, &topfd);
  442.                 if ( thisfd == bottomfd ) 
  443.                     SET_WIN();
  444.             }
  445.         }
  446.     }
  447.     finish(0);
  448. }
  449.  
  450. void reset_bar(sleeptime)
  451. int sleeptime;
  452. {
  453.     sleep(sleeptime);
  454.     vt_info(NULL);
  455. }
  456.  
  457. /* Print out a help screen for the escapes */
  458. void print_help()
  459. {
  460.     static char *help[] = {
  461. "Escape commands: ", 
  462. "    '-'    Shrink the current window",
  463. "    '+'    Expand the current window",
  464. "    'k'    Kill the current window",
  465. "    'r'    Refresh the screen",
  466. "    'c'    Copy selection",
  467. "    'p'    Paste selection",
  468. "    'x'    Lock the screen",
  469. "    'h'    Show this help screen",
  470. "    'q'    Quickly quit splitvt",
  471. NULL
  472. };
  473.     vt_showscreen("Splitvt HELP screen:", help);
  474. }
  475.  
  476. void normal_input(c)
  477. char c;
  478. {
  479.     char message[BUFSIZ];
  480.     int pid;
  481.     static int param=0;
  482.  
  483.     if ( c == quote_c ) {
  484.         read(ttyfd, &c, 1);
  485.         goto writeit;
  486.     } else if ( c == switch_c ) {
  487.         if ( (thisfd == topfd) && bottomok )
  488.             thisfd=bottomfd;
  489.         else if ( topok )
  490.             thisfd=topfd;
  491.         SET_WIN();
  492.     } else if ( c == command_c ) {
  493. promptch:
  494.         c=vt_prompt(PROMPT);
  495.         switch (c) {
  496.             /* Shrink current window */
  497.             case '-': if ( ! param )
  498.                     param=1;
  499.                   move_bar(thisfd == topfd ? -param : param);
  500.                   param=0;
  501.                   break;
  502.             /* Grow current window */
  503.             case '+': if ( ! param )
  504.                     param=1;
  505.                   move_bar(thisfd == topfd ? param : -param);
  506.                   param=0;
  507.                   break;
  508.             /* Kill a window */
  509.             case 'k': sprintf(message, "Kill %s window? [Y/n]: ",
  510.                     (thisfd == topfd) ? "upper" : "lower");
  511.                   switch(vt_prompt(message)) {
  512.                     case 'N':
  513.                     case 'n': break;
  514.                     /* Kill with hangup signal */
  515.                     default:  pid=((thisfd == topfd) ? 
  516.                             toppid : bottompid);
  517.                           (void) kill(pid, SIGHUP);
  518.                           break;
  519.                   }
  520.                   vt_info(NULL);
  521.                   break;
  522.             /* Copy selection */
  523.             case 'c': vt_getsel(CUR_WIN(), selection, BUFSIZ);
  524.                   reset_bar(1);
  525.                   break;
  526.             /* Paste selection */
  527.             case 'p': write(thisfd, selection, strlen(selection));
  528.                   break;
  529.             /* Lock the screen */
  530.             case 'x': vt_info("Enter password: ");
  531.                   do_input=lock_screen;
  532.                   break;
  533.             /* Repaint the screen */
  534.             case 'r': vt_redraw();
  535.                   break;
  536.             /* Quick exit */
  537.             case 'q': finish(0);
  538.                   break;
  539.             /* Print a quick help screen */
  540.             case '?':
  541.             case 'h': print_help();
  542.                   break;
  543.             case '0':
  544.             case '1':
  545.             case '2':
  546.             case '3':
  547.             case '4':
  548.             case '5':
  549.             case '6':
  550.             case '7':
  551.             case '8':
  552.             case '9': /* Set numeric parameter */
  553.                   param *= 10;
  554.                   param += (c-'0');
  555.                   goto promptch;
  556.                   break;
  557.             default:  break;
  558.         }
  559.     }
  560.     else { writeit:
  561.         write(thisfd, &c, 1);
  562.     }
  563. }
  564.  
  565. /* A better child checker. :)  It gathers the status of the child,
  566.    rendering it free and un-zombied. :) */
  567.  
  568. static int isalive()
  569. {
  570.     int status;
  571.  
  572. #if ! defined(WNOHANG) || defined(NEED_INET_H)
  573.     if ( topok )
  574.         if (  kill(toppid, 0) < 0 )
  575.         {
  576.             if ( pw ) 
  577.                 (void) delutmp(pw->pw_name, upper_tty);
  578.             if ( thisfd == topfd )
  579.                 thisfd=bottomfd;
  580.             (void) close(topfd);
  581.             topok=0;
  582.             SET_WIN();
  583.         }
  584.  
  585.     if ( bottomok )
  586.         if ( kill(bottompid, 0) < 0 )
  587.         {
  588.             if ( pw ) 
  589.                 (void) delutmp(pw->pw_name, lower_tty);
  590.             if ( thisfd == bottomfd )
  591.                 thisfd=topfd;
  592.             (void) close(bottomfd);
  593.             bottomok=0;
  594.             SET_WIN();
  595.         }
  596.  
  597. #else
  598. #ifdef HAVE_WAIT4    /* For BSD 4.3 */
  599. #define waitpid(pid, status, options)    wait4(pid, status, options, NULL)
  600. #endif /* HAVE_WAIT4 */
  601.  
  602.     if ( topok )
  603.         if ( waitpid(toppid, &status, WNOHANG) != 0 )
  604.         {
  605.             if ( pw ) 
  606.                 (void) delutmp(pw->pw_name, upper_tty);
  607.             if ( thisfd == topfd )
  608.                 thisfd=bottomfd;
  609.             (void) close(topfd);
  610.             topok=0;
  611.             SET_WIN();
  612.         }
  613.  
  614.     if ( bottomok )
  615.         if ( waitpid(bottompid, &status, WNOHANG) != 0 )
  616.         {
  617.             if ( pw ) 
  618.                 (void) delutmp(pw->pw_name, lower_tty);
  619.             if ( thisfd == bottomfd )
  620.                 thisfd=topfd;
  621.             (void) close(bottomfd);
  622.             bottomok=0;
  623.             SET_WIN();
  624.         }
  625. #endif
  626.     if ( topok || bottomok )
  627.         return(1);
  628.     return(0);
  629. }
  630.  
  631.     
  632. /* Cleanup routine */
  633. static void finish(sig)
  634. int sig;
  635. {
  636.     /* Only call this routine after tty_getmode() has been called */
  637.     /* The tty_reset() call flushes the tty's input buffers. */
  638.     if ( tty_reset(0) < 0 )    
  639.         (void) tty_sane(0);
  640.  
  641.     /* Reset the vt100 window */
  642.     end_vt100();
  643.     event_quit();
  644.  
  645.     /* Reset our utmp entries */
  646.     if ( pw && topok && upper_tty[0] )
  647.         (void) delutmp(pw->pw_name, upper_tty);
  648.     if ( pw && bottomok && lower_tty[0] )
  649.         (void) delutmp(pw->pw_name, lower_tty);
  650.     (void) replace_me();
  651.  
  652.     if ( sig )
  653.         printf("Exiting due to signal: %d\n", sig);
  654.     exit(sig);
  655. }
  656.  
  657. /* Move the separator bar up and down.  We can do this now, because
  658.    init_vt100() properly refreshes the screen (we hope) ;-)
  659. */
  660.  
  661. static void move_bar(howfar)
  662. int howfar;
  663. {
  664.     int tmp_uulines;
  665.  
  666.     tmp_uulines=UU_lines;
  667.     UU_lines=WU_lines;
  668.     UU_lines += howfar;    /* Positive to go down, negative to go up */
  669.     init_vt100();        /* Reset the windows to the new size */
  670.  
  671.     /* Tell the running processes about the size change */
  672.     if ( topfd )
  673.         pty_setwin(topfd, UPPER);
  674.     if ( bottomfd )
  675.         pty_setwin(bottomfd, LOWER);
  676.     UU_lines=tmp_uulines;
  677. }    
  678.  
  679. /* Resize the window... unfortunately, this means that the
  680.    current window is erased.  Oh well.. :)
  681.    Ah hah!  As of 1.6.0, the window is refreshed. :)
  682.  */
  683.  
  684. static void winch(sig)
  685. int sig;
  686. {
  687.     char *ptr;
  688.  
  689.     signal(sig, winch);
  690.  
  691.     if ( (ptr=init_vt100()) != NULL ) {
  692.         fprintf(stderr, "Can't resize window: %s. (exiting)\n", ptr);
  693.         finish(0);
  694.     } else
  695.         SET_WIN();
  696.     if ( topfd )
  697.         pty_setwin(topfd, UPPER);
  698.     if ( bottomfd )
  699.         pty_setwin(bottomfd, LOWER);
  700. }
  701.  
  702. static int insert_dash(args)
  703. char *args[];
  704. {
  705.     char *temp;
  706.  
  707.     if ( (temp=(char *)malloc(strlen(args[0])+2)) == NULL )
  708.         return(-1);
  709.     sprintf(temp, "-%s", args[0]);
  710.     args[0]=temp;        /* Possible memory leak.. who cares? */
  711.     return(0);
  712. }
  713.